#include <jni.h>
#include <string>
#include "MyGLRenderContext.h"
#include "LogUtil.h"

#define CLASS_NAME "com/uestc/demotriangle/GLTestLib"

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL native_init(JNIEnv *env, jobject instance) {
    LOGCATD("native_init invoked!");
    MyGLRenderContext::getInstance()->onSurfaceCreated();
}

void native_resize(JNIEnv *env, jobject instance, jint width, jint height ) {
    LOGCATD("native_resize invoked! width: %d; height: %d", width, height);
    MyGLRenderContext::getInstance()->onSurfaceChanged(width, height);
}

JNIEXPORT void JNICALL native_drawFrame(JNIEnv *env, jobject instance) {
//    LOGCATD("native_drawFrame invoked!");
    MyGLRenderContext::getInstance()->onDrawFrame();
}

#ifdef __cplusplus
}
#endif

extern "C" JNIEXPORT jstring JNICALL
Java_com_uestc_demotriangle_GLTestLib_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

static JNINativeMethod glRenderMethods[] = {//这里的V一定要用大写V，小写是错误的。
        {"native_init", "()V", (void*)native_init},
        {"native_resize", "(II)V", (void*)native_resize},
        {"native_drawFrame", "()V", (void*)native_drawFrame},
};

static int registerNativeMethod(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodNum) {
    LOGCATD("register native method");
    jclass clazz = env->FindClass(className);
    if (clazz == NULL) {
        LOGCATE("register native method failed, can not find %s", className);
        return JNI_FALSE;
    }

    jint registerStatus = env->RegisterNatives(clazz, methods, methodNum);
    if (registerStatus < 0) {
        LOGCATE("register native method failed, class: %s, registerStatus: %d, methodNum: %d", className, registerStatus, methodNum);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

static void unRegisterNativeMethod(JNIEnv *env, const char *className) {
    LOGCATD("unregister native method");
    jclass clazz = env->FindClass(className);
    if (clazz == NULL) {
        LOGCATE("unregister native method failed, can not find %s", className);
        return;
    }
    env->UnregisterNatives(clazz);
}

extern "C" jint JNI_OnLoad(JavaVM *jvm, void *p) {
    LOGCATD("JNI_OnLoad function invoked!");
    jint jniRet = JNI_ERR;
    JNIEnv *env = NULL;
    if (jvm->GetEnv((void **)(&env), JNI_VERSION_1_6) != JNI_OK) {
        LOGCATD("JNI_OnLoad can not get JNIEnv instace");
        return JNI_ERR;
    }
    int regStatus = registerNativeMethod(env, CLASS_NAME, glRenderMethods, sizeof(glRenderMethods)/
                                                                           sizeof(glRenderMethods[0]));
    if (regStatus != JNI_TRUE) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

extern "C" void JNI_OnUnload(JavaVM *jvm, void *p) {
    JNIEnv *env = NULL;
    if (jvm->GetEnv((void **)(&env), JNI_VERSION_1_6) != JNI_OK) {
        return;
    }
    unRegisterNativeMethod(env, CLASS_NAME);
}
